#include "exportapi.h"

#include "app_inneltest.h"
// dear imgui: standalone example application for DirectX 9
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.

#include "../imgui/imgui.h"

//#include "imgui_impl_win32.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_bfgx.h"
#include "bgfx/bgfx.h"
#include "bgfx/platform.h"
#include "SDL2/SDL.h"
#include "SDL2/SDL_syswm.h"
#include <string>
#include "../stringtool/stringconv.h"
//#include <d3d9.h>
//#define DIRECTINPUT_VERSION 0x0800
//#include <dinput.h>
//#include <Windows.h>

EXPORT_API void SetAssertCallBack(deleOnIMAssertU16 callback)
{
	onImAssert = callback;
}
//// Data
//static LPDIRECT3D9              g_pD3D = NULL;
//static LPDIRECT3DDEVICE9        g_pd3dDevice = NULL;
//static D3DPRESENT_PARAMETERS    g_d3dpp = {};
//
//// Forward declarations of helper functions
//bool CreateDeviceD3D(HWND hWnd);
//void CleanupDeviceD3D();
//void ResetDevice();
//LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void MsgProc(SDL_Event &event, int mainwin);
static bool bExit = false;
static deleOnLog g_logger = NULL;
static inline void Log(const char16_t *log)
{
	if (g_logger != NULL)
		g_logger(log);
}
EXPORT_API int APP_SetLogger(deleOnLog logger)
{
	g_logger = logger;
}
// Main code
EXPORT_API int App_MainLoop(const char16_t *winTitle, deleOnInit onInit, deleOnUpdate onUpdate, deleOnGUI onGUI, deleOnExit onExit)
{
	//ImGui_ImplWin32_EnableDpiAwareness();

	//��windows �� char16_t ���� wchar_t
	//��linux�¾�Ҫ��std::u16string
	Log(u"App_MainLoop 00");
	// Create application window
	SDL_Init(SDL_INIT_VIDEO);
	std::string strTitle = StringConv::ToUtf8String(winTitle);
	Uint32 sdl_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
	sdl_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
	SDL_Window *winMain = SDL_CreateWindow(strTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 800, sdl_flags);

	// WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, (const wchar_t *)winTitle, NULL};
	// ::RegisterClassEx(&wc);
	// HWND hwnd = ::CreateWindow(wc.lpszClassName, (const wchar_t *)winTitle, WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);

	// Initialize Direct3D

	// Show the window
	// ::ShowWindow(hwnd, SW_SHOWDEFAULT);
	// ::UpdateWindow(hwnd);
	// Setup Dear ImGui context
	IMGUI_CHECKVERSION();
	ImGui::CreateContext();
	ImGuiIO &io = ImGui::GetIO();
	(void)io;
	io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
	//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
	io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;	// Enable Docking
	//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
	//io.ConfigViewportsNoAutoMerge = true;
	//io.ConfigViewportsNoTaskBarIcon = true;

	// Setup Dear ImGui style
	ImGui::StyleColorsDark();
	//ImGui::StyleColorsClassic();

	// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
	ImGuiStyle &style = ImGui::GetStyle();
	if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
	{
		style.WindowRounding = 0.0f;
		style.Colors[ImGuiCol_WindowBg].w = 1.0f;
	}

	// Setup Platform/Renderer bindings
	//ShowWindow֮��ߴ�ᷢ���仯����ʱ��GetWindowRect�õ��ĳߴ粻һ��
	//ImGui_ImplWin32_Init(hwnd);

	ImGui_ImplSDL2_Init(winMain);

	int realw = -1;
	int realh = -1;
	SDL_GetWindowSize(winMain, &realw, &realh);
	bgfx::PlatformData pdata;
	SDL_SysWMinfo info;
	SDL_VERSION(&info.version);
	if (SDL_GetWindowWMInfo(winMain, &info))
	{
		if (info.subsystem == SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS)
		{
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
			main_viewport->PlatformHandleRaw = (void *)info.info.win.window;
#endif
		}
		else if (info.subsystem == SDL_SYSWM_TYPE::SDL_SYSWM_X11)
		{
#if defined(SDL_VIDEO_DRIVER_X11)
			pdata.ndt = info.info.x11.display;
			pdata.nwh = (void *)info.info.x11.window;
#endif
		}
		else if (info.subsystem == SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND)
		{
#if defined(SDL_VIDEO_DRIVER_WAYLAND)
			pdata.ndt = info.info.wl.display;
			pdata.nwh = (void *)info.info.wl.surface;
#endif
		}
		else
		{
			throw "only support x11 fornow.";
		}
	}
	ImGui_ImplBgfx_Init(pdata, realw, realh);

	onInit();
	Log(u"after onInit");
	app_inneltest::onInit();
	Log(u"after app_inneltest::onInit");
	ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
	// Main loop
	int mainWinID = SDL_GetWindowID(winMain);
	SDL_Event event;
	while (!bExit)
	{
		int b = SDL_PollEvent(&event);

		if (b)
		{
			ImGui_ImplSDL2_ProcessEvent(&event);
			MsgProc(event, mainWinID);
		}
		else
		{
			onUpdate();
			app_inneltest::onUpdate();
			{ //Editor Frame

				Frame_SetMainScreen();
				Frame_Clear(0, true, true);
				// Start the Dear ImGui frame
				//ImGui_ImplDX9_NewFrame();
				ImGui_ImplBgfx_NewFrame();
				ImGui_ImplSDL2_NewFrame(winMain);
				//ImGui_ImplWin32_NewFrame();
				{
					ImGui::NewFrame();

					onGUI();
					app_inneltest::onEditorGUI();

					ImGui::EndFrame();
				}
				ImGui::Render(); //����IMGUIDrawData
				ImGui_ImplBgfx_RenderDrawData(ImGui::GetDrawData());

				// Update and Render additional Platform Windows
				if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
				{
					ImGui::UpdatePlatformWindows();
					ImGui::RenderPlatformWindowsDefault();
				}
			}
		}
	}

	onExit();
	app_inneltest::onExit();

	//ImGui_ImplDX9_Shutdown();
	ImGui::DestroyContext();

	ImGui_ImplBgfx_Shutdown();
	//ImGui_ImplWin32_Shutdown();
	ImGui_ImplSDL2_Shutdown();
	//CleanupDeviceD3D();
	// ::DestroyWindow(hwnd);
	// ::UnregisterClass(wc.lpszClassName, wc.hInstance);
	SDL_DestroyWindow(winMain);
	return 0;
}

// Forward declare message handler from imgui_impl_win32.cpp
//extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void MsgProc(SDL_Event &event, int mainwin)
{
	switch (event.type)
	{
	case SDL_EventType::SDL_WINDOWEVENT:

	{
		switch (event.window.event)
		{
		case SDL_WINDOWEVENT_CLOSE:
			if (event.window.windowID == mainwin)
			{
				bExit = true;
			}
			break;
		case SDL_WINDOWEVENT_RESIZED:
			if (event.window.windowID == mainwin)
			{
				bgfx::reset(event.window.data1, event.window.data2, BGFX_RESET_VSYNC);
			}
			break;
		}
	}
	break;

	default:
		break;
	}
}
// Win32 message handler
// LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
// {
// 	if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
// 		return true;

// 	switch (msg)
// 	{
// 	case WM_SIZE:
// 		realw = LOWORD(lParam);
// 		realh = HIWORD(lParam);
// 		if (bgfxinited && wParam != SIZE_MINIMIZED)
// 		{
// 			bgfx::reset(realw, realh);
// 			bgfx::setViewRect(0, 0, 0, realw, realh);
// 		}
// 		return 0;
// 	case WM_SYSCOMMAND:
// 		if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
// 			return 0;
// 		break;
// 	case WM_DESTROY:
// 		::PostQuitMessage(0);
// 		return 0;
// 	case WM_DPICHANGED:
// 		if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
// 		{
// 			//const int dpi = HIWORD(wParam);
// 			//printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
// 			const RECT *suggested_rect = (RECT *)lParam;
// 			::SetWindowPos(hWnd, NULL, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
// 		}
// 		break;
// 	}
// 	return ::DefWindowProc(hWnd, msg, wParam, lParam);
// }
